<?php
namespace app\api\controller;
use app\common\controller\ApiBase;
use app\common\library\ErrorType;
use app\common\library\YuUtil;
use app\common\model\UrlPublic;
use think\Exception;
use think\Db;

/**
 * @title 公共Url 类
 * @description public URL 管理
 * @package app\api\controller
 */
class Yudata extends ApiBase
{
    /**
     * @var 用户登陆的id
     */
    protected $uid;
    /**
     * @var array 前置操作，这里是检查登录
     */
    protected $beforeActionList = [
        'checkAuth'
    ];

    /**
     * @title 检查登录
     * @description 检查登录
     * @author Admin ldy
     * @param name:token  type:string require:1 default:1 desc:
     * @time 2018/9/19  9:36
     */
    protected function checkAuth(){
        /// 如需登录，调用此方法鉴权
        /// 注解1：如果已经登录，则会获取到uid;否则会直接打印错误信息，不执行下面的代码
        /// 注解2：该方法走的是缓存，不通过数据库检查
        /// 注解3：如果没有token信息，需要调登录接口，重新获取token，并保存，token有效期暂定为30天
        /// 注解4：该类所有方法需要登录鉴权，故预先加载
        $this->uid = $this->getUidByCheck();
    }

    /**
     * @title 新增公共url(自动)
     * @description 新增公共url，自动获取传入的url的title数据（比较消耗资源）
     * @author Admin ldy
     * @url /api/yudata/yuadd
     * @param name:u  type:string require:1 default:1 desc:核心数据
     * @param name:token  type:string require:1 default:1 desc:身份验证
     * @time 2018/9/19  8:46
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function yuadd(){
        $this->yuAddBase2();
    }

    /**
     * @title url_data_json参数的样式
     * @description url_data_json参数的样式
     * @author Admin ldy
     * @url /api/yudata/demoJson
     * @param name:token  type:string require:1 default:1 desc:
     * @time 2018/9/20  17:04
     */
    public function demoJson(){
        $jsondemo ="{\"url\":\"https:\/\/www.cnblogs.com\/xinweiyun\/p\/7801833.html\",\"content_type\":\"text\/html; charset=utf-8\",\"http_code\":200,\"header_size\":340,\"request_size\":381,\"filetime\":-1,\"ssl_verify_result\":20,\"redirect_count\":0,\"total_time\":0.453,\"namelookup_time\":0.031,\"connect_time\":0.063,\"pretransfer_time\":0.406,\"size_upload\":0,\"size_download\":9154,\"speed_download\":20207,\"speed_upload\":0,\"download_content_length\":9154,\"upload_content_length\":-1,\"starttransfer_time\":0.453,\"redirect_time\":0,\"redirect_url\":\"\",\"primary_ip\":\"101.37.113.127\",\"certinfo\":[],\"primary_port\":443,\"local_ip\":\"192.168.14.136\",\"local_port\":50602,\"page_info\":{\"site_title\":\"php\u6d88\u606f\u961f\u5217\u4e4b think queue\u6d88\u606f\u961f\u5217\u521d\u4f53\u9a8c - \u79cb\u5cf0\u4e0d\u662f\u98ce - \u535a\u5ba2\u56ed\",\"site_description\":\"\",\"site_keywords\":\"\",\"friend_link_status\":0,\"site_claim_status\":0,\"site_home_size\":9154}}";

        echo $jsondemo;
    }

    /**
     * @title 新增公共url(手动)
     * @description 新增公共url，手动传入的url的title数据（消耗资源较少）
     * @author Admin ldy
     * @url /api/yudata/yuAddWithTitle
     * @param name:u  type:string require:1 default:1 desc:核心数据
     * @param name:token  type:string require:1 default:1 desc:身份验证
     * @param name:title  type:string require:1 default:1 desc:URL的标题
     * @param name:type  type:string require:1 default:1 desc:URL里面的标签数据
     * @param name:url_data_json  type:string require:1 default:1 desc:关于核心数据的一些信息，具体格式参加另一接口:url_data_json参数的样式（/api/yudata/demoJson）
     * @time 2018/9/19  8:46
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function yuAddWithTitle(){
        $this->yuAddBase2('nonautomatic');
    }

    /**
     * @title 新增公共URL的实现方法
     * @description 新增公共URL的实现方法
     * @author Admin ldy
     * @param name:type  type:string require:1 default:1 desc:URL里面的标签数据
     * @time 2018/9/20  17:17
     */
    protected function yuAddBase2($type='auto'){
        $da=$this->object_array(json_decode($this->yuaddbase()));
        //type auto：自动获取title  nonautomatic:手动提交title数据
        if ($type=='nonautomatic'){
            //如果是手动提交标题，则不需要自动获取，优化性能
            $da['title_auto'] = $this->request->param('title');
            $da['type_auto'] = $this->request->param('type');
            $da['url_data_json'] = $this->request->param('url_data_json');
        }
        try {
            //检查是否已经存在该url
            $urlpublic = UrlPublic::field('url,status_is_use,version,num_read_all,num_like,id,socre,num_collecton,num_open_pv')->where($da['con'])->find();
            if ($urlpublic) {
                //存在则只修改收藏数，而不添加一条新纪录
                $urlpublic->status_is_use = '0';//？
                $urlpublic->version = $this->addIntValue($urlpublic->version);
                $urlpublic->socre = $this->addIntValue($urlpublic->socre);
                $urlpublic->num_read_all = $this->addIntValue($urlpublic->num_read_all);
                $urlpublic->num_like = $this->addIntValue($urlpublic->num_like);
                $urlpublic->num_collecton = $this->addIntValue($urlpublic->num_collecton);
                $urlpublic->num_open_pv = $this->addIntValue($urlpublic->num_open_pv);
            } else {

                //不存在的，就新增
                $urlpublic = new UrlPublic();
                $urlpublic->url = $da['url'];
                $urlpublic->url_scheme = $da['scheme'];
                $urlpublic->url_host = $da['host'];
                $urlpublic->url_path = $da['url_path'];
                $urlpublic->key = $da['key'];
                $urlpublic->version = '01';
                $urlpublic->socre = '50';
                $urlpublic->num_read_all = 1;
                $urlpublic->num_like = 1;
                $urlpublic->num_collecton = 1;


                if ($type == 'auto') {
                    //如果是自动获取标题，则异步执行
                    //访问一次，获取title数据(次要数据插入操作，异步执行，优化速度)
                    //方法1，自己简单的实现异步调用
//                $apiString = '/api/yudata/yuDetail/';
//                $this->asynDoByUrl($apiString,array('token'=>$da['token'],'u'=>$da['url']));
                    //方法2，使用think-queue组件异步执行任务，可监控
//                $jobHandlerClassName  = 'app\common\job\AddAutoTitle';
//                $jobQueueName  	  = "yuJobQueue";
//                $jobData       	  = [ 'token' => $da['token'], 'u' => $da['url']] ;
//                $isPushed = Queue::push( $jobHandlerClassName , $jobData , $jobQueueName );
                    //方法3，封装使用，使用内存空间换取响应时间
                    $jobHandlerClassName = 'app\common\job\AddAutoTitle';
                    $jobData = ['token' => $da['token'], 'u' => $da['url']];
                    $isPushed = YuUtil::postMsg($jobHandlerClassName, $jobData);
                    if ($isPushed) {
                        $pushTime = date('Y-m-d H:i:s') . " a new AddAutoTitle Job is Pushed to the MQ" . "<br>";
                    } else {
                        $pushTime = 'Oops, something went wrong.';
                    }
                    $urlpublic->desc = $pushTime;
                }

                if ($type == 'nonautomatic') {
                    //手动提交的，新增的时候，直接插入标题数据
                    $urlpublic->title_auto = $this->format_empty($da['title_auto']);
                    $urlpublic->type_auto = $this->format_empty($da['type_auto']);
                    $urlpublic->url_data_json = $this->format_empty($da['url_data_json']);
                }
            }
            $re = $urlpublic->save();
            if ($re) {
                $this->success('新增成功',$re);
            } else {
                $this->error('新增失败');
            }
        }catch (Exception $e){
            $this->err(ErrorType::ADD_DATA_FAILED,$e->getTraceAsString());
        }
    }

    /**
     * @title 检查某条核心数据是否存在
     * @description 检查某条核心数据是否存在
     * @param name:u  type:string require:1 default:1 desc:核心数据
     * @param name:token  type:string require:1 default:1 desc:身份验证
     * @author Admin ldy
     * @url /api/yudata/checkDataExist
     * @time 2018/9/20  17:22
     */
    public function checkDataExist(){
        $da=$this->object_array(json_decode($this->yuaddbase()));
        //检查是否已经存在该url
        try {
            $urlpublic = UrlPublic::field('url,url_data_json,version,type_auto,title_auto,id,socre,num_collecton,status_is_use')->where($da['con'])->find();
            if ($urlpublic) {
                $this->success('数据存在!', $urlpublic, 200);
            } else {
                $this->error('数据不存在!');
            }
        }catch (Exception $e){
            $this->error('数据不存在!',$e->getTraceAsString());
        }
    }

    /**
     * @title 新增url的鉴权、格式化、分析、标准化数据
     * @description 新增url的鉴权、格式化、分析、标准化数据（只是格式化数据，和检查传输数据是否成功，并不会执行数据存储操作）
     * @author Admin ldy
     * @url /api/yudata/yuaddbase
     * @param name:token  type:string require:1 default:1 desc:身份验证
     * @param name:u  type:string require:1 default:1 desc:核心数据
     * @time 2018/9/20  15:57
     * @return da:json格式的数据数组
     */
    public function yuaddbase(){
        //新增公共url
        $url = $this->request->param('u');
        $token = $this->request->param('token');
        return $this->getFormatUrlParams($url,$token);
    }

    /**
     * @title 抓取标题（耗时）
     * @description 从网络中抓取页面内容，并分析获得标题，插入数据库
     * @author Admin ldy
     * @url  /api/yudata/yudetail
     * @param name:token  type:string require:1 default:1 desc:登录验证
     * @param name:u  type:string require:1 default:1 desc:核心数据
     * @time 2018/9/19  14:31
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function yuDetail(){
        $da=$this->object_array(json_decode($this->yuaddbase()));
        //访问一次，获取title数据
        $urldata = YuUtil::get_siteurl_curlinfo($da['url']);
        $status = 0;
        if ($urldata['http_code'] !=200){
            //如果http请求不通，则设置这个URL为失效
            //这里有待改进，还会有其他的情况，例如304、404这些，不能用一次请求就草率的决定，应该改进成计划任务（闲时访问，不常用的URL）
            $status = 4;
        }
        //检查是否已经存在该url
        $urlpublic = UrlPublic::field('url,url_data_json,version,type_auto,title_auto,id,socre,num_collecton,status_is_use')->where($da['con'])->find();
        if ($urlpublic){
            //存在则只修改收藏数，而不添加一条新纪录
            $urlpublic->socre = $this->addIntValue($urlpublic->socre);
            $urlpublic->version = $this->addIntValue($urlpublic->version);
            $urlpublic->title_auto = empty($urldata['page_info']['site_title'])?'':$urldata['page_info']['site_title'];//这里是有点小问题的，需要做性能优化
            $urlpublic->type_auto = empty($urldata['page_info']['site_keywords'])?'':$urldata['page_info']['site_keywords'];//这里是有点小问题的，需要做性能优化
            $urlpublic->url_data_json = json_encode($urldata);
            $urlpublic->status_is_use = $status;
        }else{
            //不存在的，就新增
            $urlpublic = new UrlPublic();
            $urlpublic->url = $da['url'];
            $urlpublic->url_scheme = $da['scheme'];
            $urlpublic->url_host = $da['host'];
            $urlpublic->url_path = $da['url_path'];
            $urlpublic->key = $da['key'];
            $urlpublic->version = '01';
            $urlpublic->socre = '50';
            $urlpublic->num_read_all = 1;
            $urlpublic->num_like = 1;
            $urlpublic->num_collecton = 1;
            $urlpublic->title_auto = empty($urldata['page_info']['site_title'])?'':$urldata['page_info']['site_title'];//这里是有点小问题的，需要做性能优化
            $urlpublic->type_auto = empty($urldata['page_info']['site_keywords'])?'':$urldata['page_info']['site_keywords'];//这里是有点小问题的，需要做性能优化
            $urlpublic->url_data_json = json_encode($urldata);
        }
        $re=$urlpublic->save();
        if ($re){
            $this->success('异步插入成功');
        }else{
            $this->error('新增失败');
        }
    }

    /**
     * @title 根据公共id，查出一条公共URL记录
     * @description 根据公共id，查出一条公共URL记录
     * @author Admin ldy
     * @url /api/yudata/getDataById
     * @param name:token  type:string require:1 default:1 desc:身份验证
     * @param name:id  type:string require:1 default:1 desc: 公共表的ID
     * @time 2018/10/12  11:41
     */
    public function getDataById(){
        $id = $this->request->param('id');
        $this->checkEmptyParams($id);
        $where = array(
            'id'=>$id,
        );
        try{
            $arr = Db::table('scj_url_public')
                ->where($where)
                ->select();
            if ($arr){
                $this->success('数据获取成功！',$arr,200);
            }else{
                $this->err(ErrorType::DATA_EXCEPTION);
            }
        }catch (Exception $e){
            $this->err(ErrorType::ACTION_FAILED,$e->getTraceAsString());
        }
    }





}
